package com.itjiange.utils;

import cn.hutool.core.util.StrUtil;
import com.itjiange.model.ExecuteMessage;
import org.springframework.stereotype.Component;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * 进程工具类
 * @author ItJianGe
 * @data 2024/3/26 10:43
 */
@Component
public class ProcessUtil {

    public static ExecuteMessage runProcessInfo(Process compileProcess, String optionName) {

        ExecuteMessage executeMessage = new ExecuteMessage();

        try {
            StopWatch stopWatch = new StopWatch(); // 创建计时器，获取代码执行时间
            stopWatch.start();

            int flag = compileProcess.waitFor(); // 错误码，判断是否成功
            executeMessage.setExitVale(flag);
            // 从当前执行的线程中获取输入流
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(compileProcess.getInputStream()));
            if (flag == 0) {
                System.out.println(optionName + "成功");
                // 从输入流中获取代码编译信息
                String compileOutputMsg;
                List<String> compileOutputStrList = new ArrayList<>();
                while ((compileOutputMsg = bufferedReader.readLine()) != null) {
                    compileOutputStrList.add(compileOutputMsg);
                }
                executeMessage.setMessage(StrUtil.join("\n", compileOutputStrList));
            } else {
                System.out.println(optionName + "失败，错误码：" + flag);
                // 从输入流中获取代码编译信息
                String compileOutputMsg;
                List<String> compileOutputStrList = new ArrayList<>();
                while ((compileOutputMsg = bufferedReader.readLine()) != null) {
                    compileOutputStrList.add(compileOutputMsg);
                }
                executeMessage.setMessage(StrUtil.join("\n", compileOutputStrList));

                // 从当前执行的线程中获取错误输入流
                BufferedReader bufferedReaderError = new BufferedReader(new InputStreamReader(compileProcess.getErrorStream()));
                // 从输入流中获取代码编译信息
                String compileOutputErrorMsg;
                List<String> compileOutputErrorStrList = new ArrayList<>();
                while ((compileOutputErrorMsg = bufferedReaderError.readLine()) != null) {
                    compileOutputErrorStrList.add(compileOutputErrorMsg);
                }
                executeMessage.setMessage(StrUtil.join("\n", compileOutputErrorStrList));
            }
            stopWatch.stop();
            executeMessage.setTime(stopWatch.getTotalTimeMillis());
            executeMessage.setMemory(256L);
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return executeMessage;
    }

    /**
     * 需要与控制台交互时
     * @param runProcess
     * @param optionName
     * @param args
     * @return
     */
    public static ExecuteMessage runProcessInfo(Process runProcess, String optionName, String args) {

        ExecuteMessage executeMessage = new ExecuteMessage();

        try {
            // 向控制台中输入程序
            OutputStream outputStream = runProcess.getOutputStream();
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream);
            String[] s = args.split(" ");
            String join = StrUtil.join("\n", s) + "\n";
            outputStreamWriter.write(join);
            outputStreamWriter.flush();

            int flag = runProcess.waitFor(); // 错误码，判断是否成功
            executeMessage.setExitVale(flag);

            System.out.println(optionName + "成功");
            // 从当前执行的线程中获取输入流
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(runProcess.getInputStream()));
            // 从输入流中获取代码编译信息
            String compileOutputMsg;
            StringBuilder compileOutputStringBuilder = new StringBuilder();
            while ((compileOutputMsg = bufferedReader.readLine()) != null) {
                compileOutputStringBuilder.append(compileOutputMsg);
            }
            executeMessage.setMessage(compileOutputStringBuilder.toString());

            outputStream.close();
            outputStreamWriter.close();
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return executeMessage;
    }
}
